#include "Config.h"
#include <exception/NpException.h>
#include <stdio.h>
#include <pugixml/include/pugixml.hpp>

using namespace std;
using namespace configInfo;
using namespace npexception;

//static char g_lastupdate[] = "/configs/config[@id]='%s'";
static const char g_generalConFileName[] = "config.xml";
static const char g_onoffConfFileName[] = "onoff.xml";
static const char g_selectPath[] = "/configs/config";
static const char g_onoffPath[] = "/onoff";

Config::Config() : XmlConfBase(g_generalConFileName)
{
  reset();
}

Config::~Config()
{
  reset();
}

Config* Config::getInstance()
{
  static Config* singleton = new Config();
  return singleton;
}

void Config::initializeConfigs()
{
  XmlConfBase::initializeConfigs(m_filePath);
}

void Config::todo(const pugi::xml_document &pugixml)
{
  m_pugixml.reset(pugixml);
  reset();
  static pugi::xpath_node_set nodeSet;
  nodeSet.empty();
  nodeSet = pugixml.select_nodes(g_selectPath);
  for (size_t i = 0; i < nodeSet.size(); ++i)
  {
    static ConfigInfo* node;
    node = new ConfigInfo();
    fillNode(nodeSet[i], *node);
    m_configs[node->flag] = node;
  }
}

void Config::fillNode(const pugi::xpath_node &src, configInfo::ConfigInfo &des)
{
  des.isactive =   atoi(getValueFromNode(src, "isactive"));
  des.sort = atoi(getValueFromNode(src, "sort"));
  des.flag = getValueFromNode(src, "flag");
  des.domain = getValueFromNode(src, "domain");
  des.targetdomain = getValueFromNode(src, "targetdomain");
  des.webname = getValueFromNode(src, "webname");
  des.filepath = getValueFromNode(src, "filepath");
  des.connstring = getValueFromNode(src, "connstring");
  des.targetconnstring = getValueFromNode(src, "targetconnstring");
  des.repeatmax = atoi(getValueFromNode(src, "repeatmax"));
  des.sleeptimes = atoi(getValueFromNode(src, "sleeptimes"));
  des.sleepbook = atoi(getValueFromNode(src, "sleepbook"));
  des.sleepchapter = atoi(getValueFromNode(src, "sleepchapter"));
  des.charset = getValueFromNode(src, "charset");
  des.lastupdate = getValueFromNode(src, "lastupdate");
  des.doclastupdate = getValueFromNode(src, "doclastupdate");
  des.sourceflag = getValueFromNode(src, "sourceflag");
  des.sourcefilepath = getValueFromNode(src, "sourceflagpath");
  des.ruleflag = getValueFromNode(src, "ruleflag");
  des.maxpage = atoi(getValueFromNode(src, "maxpage"));
  des.secondrules = getValueFromNode(src, "secondrules");
}

char* Config::getValueFromNode(const pugi::xpath_node &node, const char *key)
{
  char* tmp = reinterpret_cast<char*>(const_cast<pugi::char_t*>(node.node().child_value(key)));
  return checkPtr(tmp);
}

int Config::getOffon() throw (int)
{
  static pugi::xml_document doc;
  doc.empty();
  static std::string conf;
  combine(g_onoffConfFileName, conf);
  npexception::throwExIf(doc.load_file(conf.c_str()) == false, npexception::ONOFF_CONFIG_FILE_LOAD_ERROR);
  pugi::xml_node onff = doc.child("onoff");
  return atoi(onff.first_child().value());
}

void Config::reset()
{
  for (ConfigMapIterator it = m_configs.begin(); it != m_configs.end(); ++it)
  {
    if (it->second != NULL)
    {
      delete it->second;
    }
  }
  m_configs.clear();
}

ConfigInfo* Config::getConfig(const std::string &flag)
{
  static ConfigMapIterator it;
  it = m_configs.find(flag);
  throwExIf(it == m_configs.end(), INVALID_CONFIG_FLAG);
  return it->second;
}

ConfigInfo* Config::getConfig()
{
  return getConfig("nptest");
}

ConfigInfo* Config::getConfig(int index)
{
  bool option = (index >= static_cast<int>(m_configs.size()) || index < 0);
  throwExIf(option == true, INVALID_INDEX);
  ConfigMapIterator it = m_configs.begin();
  for (int i = 0; i < index; ++i, ++it) {}
  return it->second;
}

void Config::setLastUpdate(const std::string &value, const std::string &flag)
{
  static pugi::xpath_node_set nodes;
 nodes = m_pugixml.select_nodes(g_selectPath);
 getConfig(flag)->lastupdate = value;
 for (size_t i = 0; i < m_configs.size(); ++i)
 {
   static pugi::xpath_node node;
   node = nodes[i];
   if (memcmp(node.node().child("flag").child_value(), flag.c_str(), flag.length()) == 0)
   {
     node.node().child("lastupdate").last_child().set_value(value.c_str());
     break;
   }
 }
}

void Config::saveXml(const std::string& value, const std::string& flag)
{
  setLastUpdate(value, flag);
  m_pugixml.save_file(m_filePath.c_str(), NULL, NULL, pugi::encoding_utf8);
}

int Config::getSize()
{
  return m_configs.size();
}
